﻿/****************************************************************
*   作者：Morain
*   创建时间：2018/2/10 23:02:24
*   描述说明：
*****************************************************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace ETSModel
{
  /// <summary>
  /// 解析状态
  /// </summary>
  internal enum ParserState
  {
    PacketSize,
    PacketBody
  }

  /// <summary>
  /// 包的标识
  /// </summary>
  public enum PacketFlag
  {
    None = 0x00, // 一般包
    Reply = 0x40, // RPC应答
    RPC = 0x80 // RPC调用
  }

  /// <summary>
  /// 一个包
  /// 普通包： | 标志 | 操作类型 | 数据 |
  /// RPC 包：| 标志 | 操作类型 | RPC_ID | 数据 |
  /// </summary>
  public struct Packet
  {
    public const int MinSize = 2;
    public const int OpcodeIndex = 1; // 1-2下标是操作类型数据                                                                           
    public const int RpcIdIndex = 3;  // 3-6下标是RPCID

    public byte[] Bytes { get; }
    public ushort Length { get; set; }

    public Packet(int length)
    {
      this.Length = 0;
      this.Bytes = new byte[length];
    }

    public Packet(byte[] bytes)
    {
      this.Bytes = bytes;
      this.Length = (ushort)bytes.Length;
    }

    public byte Flag()
    {
      return this.Bytes[0];
    }

    public ushort Opcode()
    {
      return BitConverter.ToUInt16(this.Bytes, OpcodeIndex);
    }

    public uint RpcId()
    {
      return BitConverter.ToUInt32(this.Bytes, RpcIdIndex);
    }
  }

  /// <summary>
  /// 包解析器
  /// </summary>
  internal class PacketParser
  {
    private readonly RingBuffer buffer;
    private ushort packetSize;
    private ParserState state;
    private Packet packet = new Packet(ushort.MaxValue);
    private bool isOK;

    public PacketParser(RingBuffer buffer)
    {
      this.buffer = buffer;
    }

    /// <summary>
    /// 解析包
    /// </summary>
    /// <returns></returns>
    public bool Parse()
    {
      if (this.isOK)
      {
        return true;
      }

      bool finish = false;
      while (!finish)
      {
        switch (this.state)
        {
          case ParserState.PacketSize:
            if (this.buffer.Count < 2)
            {
              finish = true;
            }
            else
            {
              this.buffer.RecvFrom(this.packet.Bytes, 2);
              // 包的长度
              this.packetSize = BitConverter.ToUInt16(this.packet.Bytes, 0);
              if (this.packetSize > 60000)
              {
                throw new Exception($"packet too large, size: {this.packetSize}");
              }
              this.state = ParserState.PacketBody;
            }
            break;
          case ParserState.PacketBody:
            if (this.buffer.Count < this.packetSize)
            {
              finish = true;
            }
            else
            {
              this.buffer.RecvFrom(this.packet.Bytes, this.packetSize);
              this.packet.Length = this.packetSize;
              this.isOK = true;
              this.state = ParserState.PacketSize;
              finish = true;
            }
            break;
        }
      }
      return this.isOK;
    }

    /// <summary>
    /// 获取一个包
    /// </summary>
    /// <returns></returns>
    public Packet GetPacket()
    {
      this.isOK = false;
      return this.packet;
    }
  }
}